package com.zhihuishu.micro.course.log;

import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ch.qos.logback.classic.ClassicConstants;

import com.alibaba.dubbo.common.Constants;
import com.alibaba.dubbo.common.URL;
import com.alibaba.dubbo.common.extension.Activate;
import com.alibaba.dubbo.rpc.Filter;
import com.alibaba.dubbo.rpc.Invocation;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.Result;
import com.alibaba.dubbo.rpc.RpcException;
import com.zhihuishu.toolkit.log.LoggerTemplate;
import com.zhihuishu.toolkit.log.MDCInfoBuilder;

/**
 * 客户端接口访问日志过滤器扩展
 * 
 * @author zhanglikun
 * @date 2016年5月5日 上午9:26:09
 */
@Activate(group = { Constants.CONSUMER })
public class ConsumerLogFilter extends LogHandler implements Filter {

    protected LoggerTemplate mdcLogger = LoggerTemplate.getInstance(getClass());

    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        long start = System.currentTimeMillis();

        Result r = null;
        Exception ex = null;
        try {
            r = invoker.invoke(invocation);
        } catch (Exception e) {
            ex = e;
        }
        long end = System.currentTimeMillis();

        // 记录日志
        Class<?> inter = invocation.getInvoker().getInterface(); // 接口类型
        Logger log = LoggerFactory.getLogger("dubbo.consumer." + inter.getName()); // 日志实例

        URL url = invocation.getInvoker().getUrl();
        String host = url.getIp();
        if (StringUtils.isBlank(host))
            host = url.getHost();
        int port = url.getPort();
        final Map<String, String> params = url.getParameters();
        String pid = get(params, "pid");
        String protocol = get(params, "protocol");
        String timeout = getWithDefault(params, "timeout", "default.timeout");
        String version = getWithDefault(params, "version", "default.version");

        // 将参数列表拼装为字符串
        String parametes = concatParams(invocation.getArguments());

        MDCInfoBuilder builder = MDCInfoBuilder.create().setType("dubbo").setTag("consumer")
                .setMethodName(invocation.getMethodName()).setStartTime(start).setEndTime(end)
                .setRequestTime(end - start).put(ClassicConstants.REQUEST_REMOTE_HOST_MDC_KEY, getHost());
      // mdcLogger.info("测试日志{}",builder.build());
        mdcLogger.info(builder.build(), "测试日志组件，参数：{}", 120);
        if (ex != null) {
            mdcLogger
                    .error("接口执行失败，服务器信息：[remoteHost:{}、port:{}、pid:{}、protocol:{}、timeout:{}、version:{}]，请求参数：{}，消息：{}",
                            host, port, pid, protocol, timeout, version, parametes, ex.getMessage());
            throw new RpcException(ex);
        }
        mdcLogger.info(
                "接口执行成功，服务器信息：[remoteHost:{}、port:{}、pid:{}、protocol:{}、timeout:{}、version:{}]，请求参数：{}",
                host, port, pid, protocol, timeout, version, parametes);

        return r;
    }

}
